import React, { useEffect } from 'react'
import G6 from '@antv/g6'

let graph

let sourceAnchorIdx
let targetAnchorIdx

const CreateEdge = () => {
  useEffect(() => {
    G6.registerNode(
      'rect-node',
      {
        // draw anchor-point circles according to the anchorPoints in afterDraw
        afterDraw(cfg, group) {
          const bbox = group.getBBox()
          // this指向的是当前自定义节点
          const anchorPoints = this.getAnchorPoints(cfg)

          anchorPoints.forEach((anchorPos, i) => {
            group.addShape('circle', {
              attrs: {
                r: 5,
                x: bbox.x + bbox.width * anchorPos[0],
                y: bbox.y + bbox.height * anchorPos[1],
                fill: '#fff',
                stroke: '#5F95FF',
              },
              name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point')
              anchorPointIdx: i, // flag the idx of the anchor-point circle
              visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
              draggable: true, // allow to catch the drag events on this shape
            })
          })
        },
        getAnchorPoints(cfg) {
          return (
            cfg.anchorPoints || [
              [0, 0.5],
              [0.33, 0],
              [0.66, 0],
              [1, 0.5],
              [0.33, 1],
              [0.66, 1],
            ]
          )
        },
        // response the state changes and show/hide the link-point circles
        setState(name, value, item) {
          if (name === 'showAnchors') {
            const anchorPoints = item
              .getContainer()
              .findAll((ele) => ele.get('name') === 'anchor-point')

            anchorPoints.forEach((point) => {
              if (value) point.show()
              else point.hide()
            })
          }
        },
      },
      'rect'
    )
    createG6()
  }, [])
  const createG6 = () => {
    graph = new G6.Graph({
      container: 'container',
      width: 500,
      height: 500,
      modes: {
        default: [
          // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles
          {
            type: 'drag-node',
            shouldBegin: (e) => {
              if (e.target.get('name') === 'anchor-point') return false
              return true
            },
          },

          {
            type: 'create-edge',
            trigger: 'drag',
            shouldBegin: (e) => {
              const node = e.target
              if (node && node.get('name') !== 'anchor-point') {
                return false
              }
              sourceAnchorIdx = node.get('anchorPointIdx')

              return true
            },
            shouldEnd: (e) => {
              const node = e.target
              if (node && node.get('name') !== 'anchor-point') {
                return false
              }
              targetAnchorIdx = node.get('anchorPointIdx')
              return true
            },
          },
        ],
      },
      defaultNode: {
        type: 'rect-node',
        style: {
          fill: '#eee',
          stroke: '#ccc',
        },
      },
      defaultEdge: {
        type: 'quadratic',
        style: {
          stroke: '#F6BD16',
          lineWidth: 2,
        },
      },
    })
    graph.data({
      nodes: [
        { id: 'node1', x: 350, y: 100 },
        { id: 'node2', x: 350, y: 250 },
      ],
    })
    graph.render()
    graph.on('node:mousemove', (e) => {
      e.item
        .get('group')
        .findAll((item, key) => {
          return item.get('name') === 'anchor-point'
        })
        .forEach((ele) => {
          ele.hide()
        })
      e.item
        .get('group')
        .findAll((item, key) => {
          return (
            item.get('anchorPointIdx') ===
            e.item.getLinkPoint({ x: e.x, y: e.y }).anchorIndex
          )
        })
        .forEach((ele) => {
          ele.show()
        })
    })
    graph.on('node:mouseenter', (e) => {
      graph.setItemState(e.item, 'showAnchors', true)
    })
    graph.on('node:mouseleave', (e) => {
      graph.setItemState(e.item, 'showAnchors', false)
    })
    graph.on('node:dragenter', (e) => {
      graph.setItemState(e.item, 'showAnchors', true)
    })
    graph.on('node:dragleave', (e) => {
      graph.setItemState(e.item, 'showAnchors', false)
    })
    graph.on('node:dragstart', (e) => {
      graph.setItemState(e.item, 'showAnchors', true)
    })
    graph.on('node:dragout', (e) => {
      graph.setItemState(e.item, 'showAnchors', false)
    })
    graph.on('aftercreateedge', (e) => {
      graph.updateItem(e.edge, {
        sourceAnchor: sourceAnchorIdx,
        targetAnchor: targetAnchorIdx,
      })
    })
  }

  return <div id="container"></div>
}

export default CreateEdge
